<template>
  <div class="file-upload-container">
    <!-- 拖拽区域 -->
    <div
      class="drop-zone"
      :class="{
        'is-dragging': isDragging,
        'has-files': combinedFiles.length > 0,
        readonly: readonly
      }"
      @dragover.prevent="handleDragOver"
      @dragleave.prevent="handleDragLeave"
      @drop.prevent="handleDrop"
      @click="triggerFileInput"
    >
      <input type="file" ref="fileInput" :multiple="multiple" :accept="accept" @change="handleFileChange" style="display: none" />

      <div class="upload-content">
        <template v-if="combinedFiles.length === 0">
          <div class="upload-icon">
            <el-icon><Upload /></el-icon>
          </div>
          <p class="upload-text">{{ placeholderText }}</p>
          <p class="upload-hint" v-if="hintText">{{ hintText }}</p>
        </template>

        <div v-else class="file-list">
          <div v-for="(file, index) in combinedFiles" :key="file.uid" class="file-item" :class="file.status">
            <!-- 文件预览 -->
            <div class="file-preview" v-if="isImageFile(file)" @click.stop>
              <!-- 图片预览 -->
              <div class="preview-image">
                <el-image preview-teleported :src="getFilePreview(file)" :alt="file.name" @click.stop="previewHandle(file)" />
                <div style="display: flex;">
                  <button v-if="!disabled" class="remove-btn" title="删除文件" @click.stop="removeFile(index, $event)">
                  <el-icon><Delete /></el-icon>
                  </button>
                  <button class="remove-btn" title="下载文件" @click.stop="DownFile(index, $event)">
                    <el-icon><Download /></el-icon>
                  </button>
                </div>
              </div>
              <!-- <div class="file-name" @click.stop="downloadPDF(file)" :title="file.name">{{ file.name }}</div>-->

              <!-- 非图片文件预览                  :preview-src-list="[ convertUrl(file.url) ]" -->
              <!-- <div class="preview-icon" v-else>
                <a class="file-extension" @click.stop>{{ getFileExtension(file.name) }}</a>
              </div> -->
            </div>
            <!-- 文件操作 @click.stop="pdfPreviewHandle(file)" -->
            <div class="file-actions" v-else-if="!isImageFile(file)&&file.name">
              <div class="file-name" v-if="!file.url" @click.stop :title="file.name">{{ file.name }}</div>
              <a v-else class="file-name" href="javascript:void(0)" @click.stop="pdfPreviewHandle(file)">
                {{ file.name }}
              </a>

              <button v-if="!disabled" class="remove-btn" title="删除文件" @click.stop="removeFile(index, $event)">
                <el-icon><Delete /></el-icon>
              </button>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
  <!-- <pdfView v-model="viewPdfvisible" :pdf-url="pdfUrl" />  -->
  <el-dialog v-model="dialogVisible" append-to-body>
    <img class="preview-image-view" :src="pdfUrl" alt="Preview Image" />
  </el-dialog>
</template>

<script>
import { ref, computed, watch } from "vue";
import { convertUrl } from "@/utils/tencentCos";
import { ElMessageBox, ElMessage } from "element-plus";
import { useRouter } from "vue-router";
import pdfView from "@/components/pdfView/index.vue";

export default {
  props: {
    // 初始文件列表（用于回显）
    modelValue: {
      type: Array,
      default: () => [],
      validator: files => {
        return files.every(file => {
          // 至少需要name和url或file对象
          return file.name && (file.url || file.file);
        });
      }
    },
    // 上传接口URL
    uploadUrl: {
      type: String,
      default: ""
    },
    // 是否多选
    multiple: {
      type: Boolean,
      default: true
    },
    limit: {
      type: Number,
      default: 10
    },
    // 接受的文件类型
    accept: {
      type: String,
      default: ""
    },
    // 最大文件大小（MB）
    maxSize: {
      type: Number,
      default: 10
    },
    // 自定义请求头
    headers: {
      type: Object,
      default: () => ({})
    },
    // 额外表单数据
    formData: {
      type: Object,
      default: () => ({})
    },
    // 是否自动上传
    autoUpload: {
      type: Boolean,
      default: false
    },
    // 提示文本
    placeholderText: {
      type: String,
      default: "Drop file or click to upload"
    },
    // 辅助提示
    hintText: {
      type: String,
      default: ""
    },
    // 是否只读
    readonly: {
      type: Boolean,
      default: false
    },
    // 是否禁用
    disabled: {
      type: Boolean,
      default: false
    },
    // 是否显示上传按钮
    showUploadButton: {
      type: Boolean,
      default: true
    },
    // 图片预览宽度
    previewWidth: {
      type: Number,
      default: 80
    },
    // 图片预览高度
    previewHeight: {
      type: Number,
      default: 60
    }
  },
  components: {
    pdfView
  },
  emits: [
    "update:modelValue",
    "upload-start",
    "upload-progress",
    "upload-success",
    "upload-error",
    "file-added",
    "file-removed",
    "files-change"
  ],
  setup(props, { emit }) {
    const fileInput = ref(null);
    const isDragging = ref(false);
    const isUploading = ref(false);
    const newFiles = ref([]);
    const uploadProgress = ref(0);
    const router = useRouter();
    // 生成唯一ID
    const generateUID = () => {
      return Date.now().toString(36) + Math.random().toString(36).substr(2);
    };

    // 合并回显文件和新文件
    const combinedFiles = computed(() => {
      return [
        ...props.modelValue.map(file => ({
          ...file,
          uid: file.uid || generateUID(),
          status: "success", // 回显文件默认为成功状态
          progress: 100
        })),
        ...newFiles.value
      ];
    });
    // 上传按钮文本
    const uploadButtonText = computed(() => {
      if (isUploading.value) {
        return `uploading ${uploadProgress.value}%`;
      }
      const count = newFiles.value.filter(f => f.status === "pending").length;
      return count > 0 ? `上传 ${count} 个文件` : "开始上传";
    });

    // 获取文件扩展名
    const getFileExtension = filename => { 
      if (!filename) return "";
      return filename.split(".").pop().toLowerCase();
    };

    // 判断是否是图片文件
    const isImageFile = file => {
      const imageTypes = ["image/jpeg", "image/png", "image/gif", "image/webp"];
      const imageExtensions = [".jpg", ".jpeg", ".png", ".gif", ".webp"];
      return imageTypes.includes(file.type) || imageExtensions.includes("." + getFileExtension(file.name));
    };

    // 格式化文件大小
    const formatFileSize = bytes => {
      if (!bytes) return "0 Bytes";
      const units = ["Bytes", "KB", "MB", "GB"];
      const unitIndex = Math.floor(Math.log(bytes) / Math.log(1024));
      return `${(bytes / Math.pow(1024, unitIndex)).toFixed(2)} ${units[unitIndex]}`;
    };

    // 获取状态文本
    const getStatusText = status => {
      const statusMap = {
        pending: "等待上传",
        uploading: "上传中",
        success: "上传成功",
        error: "上传失败"
      };
      return statusMap[status] || "";
    };

    // 处理预览图加载错误
    const handlePreviewError = file => {
      file.previewError = true;
    };
    // 获取文件预览图
    const getFilePreview = file => {
      // 已有URL的直接返回
      if (file.url) return convertUrl(file.url);

      // 新文件创建ObjectURL
      if (file.file && isImageFile(file)) {
        return URL.createObjectURL(file.file);
      }

      // 默认图标
      return "";
    };
    // 验证文件
    const validateFile = file => {
      // 验证文件数量
      if (combinedFiles.value.length >= props.limit) {
        return `You can upload a maximum of ${props.limit} files`;
      }
      // 验证文件大小
      if (props.maxSize && file.size > props.maxSize * 1024 * 1024) {
        return `The file size cannot exceed ${props.maxSize}MB`;
      }

      // 验证文件类型
      if (props.accept) {
        const acceptedTypes = props.accept
          .split(",")
          .map(type => type.trim().toLowerCase())
          .filter(type => type);

        if (acceptedTypes.length > 0) {
          const fileExtension = "." + getFileExtension(file.name);
          const typeMatch = acceptedTypes.some(type => {
            // 匹配扩展名 (如 .jpg)
            if (type.startsWith(".")) {
              return fileExtension === type;
            }
            // 匹配MIME类型 (如 image/*)
            if (type.includes("/*")) {
              const [mainType] = type.split("/");
              return file.type.startsWith(mainType);
            }
            // 精确匹配MIME类型
            return file.type === type;
          });

          if (!typeMatch) {
            return `Only ${props.accept} files are supported`;
          }
        }
      }

      return null;
    };

    // 处理文件选择
    const handleFileChange = e => {
      if (props.readonly || props.disabled) return;

      const files = e.target.files;
      const error = validateFile(files[0]);
      if (error) {
        ElMessage({
          message: error,
          type: "warning"
        });
        return false;
      }
      if (files && files.length > 0) {
        addFiles(files);
      }
      e.target.value = ""; // 重置input
    };

    // 添加文件
    const addFiles = fileList => {
      const addedFiles = Array.from(fileList).map(file => {
        const error = validateFile(file);

        console.log("[ error ] >", error);
        const fileObj = {
          uid: generateUID(),
          file, // 原始File对象
          name: file.name,
          size: file.size,
          type: file.type,
          lastModified: file.lastModified,
          status: error ? "error" : "pending",
          error: error || null,
          progress: 0
        };

        // 如果是图片且没有URL，生成预览图
        if (isImageFile(fileObj)) {
          fileObj.previewUrl = URL.createObjectURL(file);
        }

        return fileObj;
      });

      if (props.multiple) {
        newFiles.value = [...newFiles.value, ...addedFiles];
      } else {
        newFiles.value = addedFiles.slice(0, 1);
      }

      emit("files-change", combinedFiles.value);
      addedFiles.forEach(file => emit("file-added", file));

      if (props.autoUpload) {
        startUpload();
      }
    };

    // 触发文件选择
    const triggerFileInput = () => {
      if (!props.readonly && !props.disabled) {
        fileInput.value.click();
      }
    };

    // 拖拽处理
    const handleDragOver = e => {
      if (props.readonly || props.disabled) return;
      isDragging.value = true;
      e.dataTransfer.dropEffect = "copy";
    };

    const handleDragLeave = () => {
      isDragging.value = false;
    };

    const handleDrop = e => {
      if (props.readonly || props.disabled) return;

      isDragging.value = false;
      const files = e.dataTransfer.files;
      if (files && files.length > 0) {
        addFiles(files);
      }
    };

    // 移除文件
    const removeFile = (index, event) => {
      event.preventDefault(); // 阻止默认行为
      event.stopPropagation(); // 阻止事件冒泡
      event.stopImmediatePropagation(); // 阻止其他相同事件监听器
      ElMessageBox.confirm("Confirm to delete the file, Continue?", "Warning", {
        confirmButtonText: "OK",
        cancelButtonText: "Cancel",
        type: "warning"
      })
        .then(() => {
          if (index < props.modelValue.length) {
            // 回显文件，从 modelValue 中移除
            const updatedFiles = [...props.modelValue];
            const removedFile = updatedFiles.slice(index, index + 1)[0];
            // emit('update:modelValue', updatedFiles);
            emit("file-removed", removedFile);
          } else {
            // 新文件，从 newFiles 中移除
            const adjustedIndex = index - props.modelValue.length;
            const removedFile = newFiles.value.splice(adjustedIndex, 1)[0];
            if (removedFile.previewUrl) {
              URL.revokeObjectURL(removedFile.previewUrl);
            }
            emit("file-removed", removedFile);
          }
        })
        .catch(() => {
          // 用户取消，不做任何操作
        });
    };
    
    // 下载文件
    const DownFile = (index, event) => {
      event.preventDefault(); // 阻止默认行为
      event.stopPropagation(); // 阻止事件冒泡
      event.stopImmediatePropagation(); // 阻止其他相同事件监听器
      let file=combinedFiles.value[index]
      downloadPDF(file);
    }

    // 清空文件
    const clearFiles = () => {
      if (props.readonly || props.disabled) return;

      // 只清空新文件，保留回显文件
      newFiles.value.forEach(file => {
        if (file.previewUrl) {
          URL.revokeObjectURL(file.previewUrl);
        }
      });
      newFiles.value = [];
      emit("files-change", combinedFiles.value);
    };

    // 开始上传
    const startUpload = async () => {
      if (props.readonly || props.disabled || isUploading.value || newFiles.value.length === 0) {
        return;
      }

      isUploading.value = true;
      uploadProgress.value = 0;

      const filesToUpload = newFiles.value.filter(f => f.status === "pending");
      emit("upload-start", filesToUpload);
    };

    // 处理上传成功
    const handleUploadSuccess = response => {
      // 假设后端返回格式: { success: true, files: [{ name, url, size, type }] }
      const uploadedFiles = response.files || [];

      // 更新文件状态
      newFiles.value = newFiles.value.map(file => {
        if (file.status === "uploading") {
          const uploadedFile = uploadedFiles.find(f => f.name === file.name) || {};
          return {
            ...file,
            ...uploadedFile,
            status: "success",
            progress: 100,
            url: uploadedFile.url || file.url
          };
        }
        return file;
      });

      emit("upload-success", response);
      emit("files-change", combinedFiles.value);
    };

    // 处理上传错误
    const handleUploadError = error => {
      console.error("上传失败:", error);

      // 更新文件状态
      newFiles.value = newFiles.value.map(file => {
        if (file.status === "uploading") {
          return {
            ...file,
            status: "error",
            error: error.message
          };
        }
        return file;
      });

      emit("upload-error", error);
      emit("files-change", combinedFiles.value);
    };
    function downloadPDF(file) {
      if (!file) return;
      ElMessageBox.confirm("Confirm to Download the file？", "Download  Information", {
        type: "warning",
        confirmButtonText: "Confirm",
        cancelButtonText: "Cancel"
      }).then(async () => {
        const newUrl = convertUrl(file.url);
        console.log('[newUrl  ] >', newUrl)
        const a = document.createElement("a");
        a.href = newUrl;
        a.download = file.name;
        a.click();
      });
    }
    // 组件卸载时清理
    const cleanup = () => {
      newFiles.value.forEach(file => {
        if (file.previewUrl) {
          URL.revokeObjectURL(file.previewUrl);
        }
      });
    };
    const viewPdfvisible = ref(false);
    const dialogVisible = ref(false);
    const pdfUrl = ref("");
    const pdfName = ref("");
    const pdfPreviewHandle = file => {
      pdfUrl.value = encodeURI(convertUrl(file.url));
      if (["pdf", "docx", "doc", "xls", "xlsx", "txt"].some(item => file.name.includes(item))) {
        window.open(router.resolve({ path: "/pdfView/index", query: { pdfUrl: pdfUrl.value } }).href, "_blank");
      } else {
        downloadPDF(file);
      }
    };
    const previewHandle = file => {
      pdfUrl.value = convertUrl(file.url);
      dialogVisible.value = true;
    };
    return {
      fileInput,
      pdfPreviewHandle,
      isDragging,
      isUploading,
      combinedFiles,
      uploadProgress,
      uploadButtonText,
      triggerFileInput,
      handleFileChange,
      handleDragOver,
      handleDragLeave,
      handleDrop,
      removeFile,
      clearFiles,
      startUpload,
      getFileExtension,
      isImageFile,
      formatFileSize,
      getStatusText,
      handlePreviewError,
      cleanup,
      getFilePreview,
      downloadPDF,
      viewPdfvisible,
      pdfName,
      pdfUrl,
      dialogVisible,
      previewHandle,
      DownFile
    };
  }
};
</script>

<style scoped>
.file-upload-container {
  width: 100%;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
}
p {
  margin: 0;
}

.drop-zone {
  border: 2px dashed #d9d9d9;
  border-radius: 8px;
  padding: 4px 10px;
  text-align: center;
  cursor: pointer;
  transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
  background-color: #fafafa;
}

.drop-zone.is-dragging {
  border-color: #1890ff;
  background-color: #e6f7ff;
}

.drop-zone.has-files {
  border-style: solid;
  border-color: #d9d9d9;
  cursor: default;
}

.drop-zone.readonly {
  cursor: default;
}

.drop-zone.disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.upload-content {
  /* min-height: 120px; */
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
}

.upload-icon {
  margin-right: 10px;
  color: #1890ff;
  font-size: 20px;
  /* margin-bottom: 16px; */
}

.upload-text {
  font-size: 14px;
  color: rgba(0, 0, 0, 0.85);
  white-space: wrap;
  /* margin-bottom: 8px; */
}

.upload-hint {
  font-size: 14px;
  color: rgba(0, 0, 0, 0.45);
}

.file-list {
  display: flex;
  width: 100%;
  text-align: left; 
}

.file-item {
  display: flex;
  align-items: center;
  background-color: #fff;
  transition: all 0.3s;
}

.file-item:hover {
  border-color: #1890ff;
}

.file-item.uploading {
  border-left: 3px solid #1890ff;
}

.file-preview {
  margin-right: 12px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
}
.preview-image {
  display: flex;
  align-items: center;
  width: v-bind('previewWidth + "px"');
  height: v-bind('previewHeight + "px"');
  background-color: #f5f5f5;
  margin-right: 4px;
}
.preview-image img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

.file-type-icon {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #1890ff;
}

.file-info {
  flex: 1;
  min-width: 0;
}

.file-name {
  font-size: 14px;
  color: rgba(0, 0, 0, 0.85);
  margin-bottom: 4px;
  white-space: wrap;
}

.file-meta {
  display: flex;
  align-items: center;
  margin-bottom: 6px;
  font-size: 12px;
}

.file-size {
  color: rgba(0, 0, 0, 0.45);
  margin-right: 8px;
}

.file-status {
  padding: 2px 6px;
  border-radius: 2px;
  font-size: 12px;
}

.file-status.uploading {
  color: #1890ff;
  background-color: #e6f7ff;
}

.file-status.success {
  color: #52c41a;
  background-color: #f6ffed;
}

.file-status.error {
  color: #f5222d;
  background-color: #fff1f0;
}

progress {
  width: 100%;
  height: 6px;
  border-radius: 3px;
  overflow: hidden;
  appearance: none;
  -webkit-appearance: none;
}

progress::-webkit-progress-bar {
  background-color: #f5f5f5;
  border-radius: 3px;
}

progress::-webkit-progress-value {
  background-color: #1890ff;
  border-radius: 3px;
  transition: width 0.3s;
}

.file-actions {
  margin: 0 4px;
  display: flex;
}

.view-btn,
.remove-btn {
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  cursor: pointer;
  color: rgba(0, 0, 0, 0.45);
  transition: all 0.3s;
  border-radius: 4px;
}

.view-btn:hover {
  color: #1890ff;
  background-color: #e6f7ff;
}

.remove-btn:hover {
  color: #1890ff;
  background-color: rgb(240, 243, 255);
}

.upload-actions {
  display: flex;
  gap: 8px;
}

.upload-button,
.cancel-button {
  height: 32px;
  padding: 0 15px;
  font-size: 14px;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.3s;
}

.upload-button {
  background-color: #1890ff;
  color: #fff;
  border: 1px solid #1890ff;
}

.upload-button:hover {
  background-color: #40a9ff;
  border-color: #40a9ff;
}

.upload-button:disabled {
  background-color: #d9d9d9;
  border-color: #d9d9d9;
  color: rgba(0, 0, 0, 0.25);
  cursor: not-allowed;
}

.cancel-button {
  background-color: #fff;
  border: 1px solid #d9d9d9;
  color: rgba(0, 0, 0, 0.65);
}

.cancel-button:hover {
  color: #1890ff;
  border-color: #1890ff;
}

.cancel-button:disabled {
  color: rgba(0, 0, 0, 0.25);
  border-color: #d9d9d9;
  cursor: not-allowed;
}
.preview-image-view {
  transform: translateX(10%);
  width: 80%;
}
</style>
